﻿using System;
using System.Collections.Generic;
using Algoritmia.DataStructures.Maps;
using Algoritmia.Utils;

namespace Algoritmia.DataStructures.Digraphs
{
    public delegate TResult WeightingFunction< in TVertex, out TResult>(TVertex vertex1, TVertex vertex2);

    public static class WeightingFunction
    {

        public static WeightingFunction<TVertex,TResult> CreateFromMap<TVertex,TResult>(IMap<Tuple<TVertex,TVertex>,TResult> map)
        {
            return (v1, v2) => map[new Tuple<TVertex, TVertex>(v1, v2)];
        }

        public static WeightingFunction<TVertex, TResult> CreateFromMapWithEdgesUndirected<TVertex, TResult>(IMap<Tuple<TVertex, TVertex>, TResult> map)
        {
            return (v1, v2) =>
                       {
                           var tp = new Tuple<TVertex, TVertex>(v1, v2);
                           return map.Contains(tp) ? map[tp] : map[new Tuple<TVertex, TVertex>(v2, v1)];
                       };
        }

        public static WeightingFunction<TVertex,TResult> CreateFromSequence<TVertex,TResult>
            (IEnumerable<KeyValuePair<Tuple<TVertex,TVertex>,TResult>> sequence, 
            Func<IEnumerable<KeyValuePair<Tuple<TVertex,TVertex>,TResult>>, IMap<Tuple<TVertex,TVertex>,TResult>> createMap = null)
        {
            createMap = createMap ?? (seq => AlgoritmiaFactory.Maps<Tuple<TVertex, TVertex>, TResult>.BuildDefault(seq));
            var map = createMap(sequence);
            return (v1, v2) => map[new Tuple<TVertex, TVertex>(v1, v2)];
        }

    }

}
